using UnityEngine;

namespace GGPhysics
{
	public class CollisionResolution
	{
		public struct LinearImpulseResult
		{
			public float angularSpeedChange;

			public float vn1;

			public Vector3 GetAngularVelocityChange(Vector3 normal)
			{
				return Vector3.Cross(normal, Vector3.down) * angularSpeedChange;
			}
		}

		public static LinearImpulseResult ResolveLinearImpulse(CollidingBody cb1, CollidingBody cb2, float un1, float un2)
		{
			LinearImpulseResult result = default(LinearImpulseResult);
			PhysicsBody body = cb1.body;
			PhysicsBody body2 = cb2.body;
			float num = PhysicsBody.Restitution(body, body2);
			float mass = cb1.mass;
			float mass2 = cb2.mass;
			float num2 = mass + mass2;
			if (body.type != 0)
			{
				float num3 = 0f;
				if (body2.type == PhysicsBody.PhysicsBodyType.StaticBody)
				{
					num3 = (0f - num) * un1;
					if (body2.physicsDefinitions.useHeightOffsetInCollision)
					{
						float distanceToSurface = body.shape.GetDistanceToSurface(Vector3.down);
						float num4 = body2.physicsDefinitions.heightOffsetRadiusFactor * distanceToSurface;
						float angularSpeedChange = (num3 - un1) * num4 / body.shape.MomentOfInertiaWithoutMass();
						result.angularSpeedChange = angularSpeedChange;
					}
				}
				else
				{
					num3 = (un1 * mass + un2 * mass2 + num * mass2 * (un2 - un1)) / num2;
				}
				result.vn1 = num3;
			}
			return result;
		}

		public static void ResolveCollision3(ref Collision collision)
		{
			CollidingBody body = collision.body1;
			CollidingBody body2 = collision.body2;
			PhysicsBody collidingBody = collision.collidingBody1;
			PhysicsBody collidingBody2 = collision.collidingBody2;
			Vector3 normalized = (collision.collisionPoint - collision.collidingBody1PositionAtCollision).normalized;
			Vector3 vector = Vector3.Cross(normalized, Vector3.up);
			float num = body.mass;
			Vector3 velocity = collidingBody.myMotion.velocity;
			float num2 = Vector3.Dot(normalized, velocity);
			float num3 = Vector3.Dot(vector, velocity);
			float num4 = body2.mass;
			Vector3 velocity2 = collidingBody2.myMotion.velocity;
			float num5 = Vector3.Dot(normalized, velocity2);
			float num6 = Vector3.Dot(vector, velocity2);
			if (collidingBody.type == PhysicsBody.PhysicsBodyType.StaticBody)
			{
				num = 0f;
				velocity = Vector3.zero;
				num2 = 0f;
				num3 = 0f;
			}
			if (collidingBody.type == PhysicsBody.PhysicsBodyType.StaticBody)
			{
				num4 = 0f;
				velocity2 = Vector3.zero;
				num5 = 0f;
				num6 = 0f;
			}
			collision.body1.transformResolution.Set(collision.body1.body.currentTransform);
			collision.body2.transformResolution.Set(collision.body2.body.currentTransform);
			if (collidingBody.type != 0)
			{
				CollidingBody cb = body;
				CollidingBody cb2 = body2;
				float num7 = num3;
				LinearImpulseResult linearImpulseResult = ResolveLinearImpulse(cb, cb2, num2, num5);
				PhysicsBody.MotionParams motionResolution = cb.motionResolution;
				motionResolution.velocity = num7 * vector + linearImpulseResult.vn1 * normalized;
				motionResolution.angularVelocity = cb.body.myMotion.angularVelocity + linearImpulseResult.GetAngularVelocityChange(normalized);
				collision.body1.motionResolution.Set(motionResolution);
				collision.body1.transformResolution.Set(cb.transformAtCollision);
			}
			if (collidingBody2.type != 0)
			{
				CollidingBody cb3 = body2;
				CollidingBody cb4 = body;
				float num8 = num6;
				LinearImpulseResult linearImpulseResult2 = ResolveLinearImpulse(cb3, cb4, num5, num2);
				PhysicsBody.MotionParams motionResolution2 = cb3.motionResolution;
				motionResolution2.velocity = num8 * vector + linearImpulseResult2.vn1 * normalized;
				motionResolution2.angularVelocity = cb3.body.myMotion.angularVelocity + linearImpulseResult2.GetAngularVelocityChange(normalized);
				collision.body2.motionResolution.Set(motionResolution2);
				collision.body2.transformResolution.Set(cb3.transformAtCollision);
			}
			Vector3 lhs = Vector3.up * collidingBody.myMotion.angularVelocity.y;
			Vector3 lhs2 = Vector3.up * collidingBody2.myMotion.angularVelocity.y;
			float num9 = Vector3.Dot(vector, Vector3.Cross(lhs, normalized));
			float num10 = Vector3.Dot(vector, Vector3.Cross(lhs2, normalized));
			num9 = collidingBody.myMotion.angularVelocity.y;
			num10 = collidingBody2.myMotion.angularVelocity.y;
			float distanceToSurface = collidingBody.shape.GetDistanceToSurface(normalized);
			float num11 = distanceToSurface * distanceToSurface;
			float num12 = num3 - num9 * distanceToSurface;
			float num13 = num6 - num10 * distanceToSurface;
			float f = num13 - num12;
			float num14 = collidingBody.shape.MomentOfInertia();
			float num15 = collidingBody2.shape.MomentOfInertia();
			float num16 = Mathf.Abs(num5 * num4 - num2 * num);
			float num17 = PhysicsBody.Restitution(collidingBody, collidingBody2);
			if (collidingBody2.type == PhysicsBody.PhysicsBodyType.StaticBody)
			{
				num16 = Mathf.Abs(num2 * num * (1f + num17));
			}
			if (collidingBody.type == PhysicsBody.PhysicsBodyType.StaticBody)
			{
				num16 = Mathf.Abs(num5 * num * (1f + num17));
			}
			float num18 = PhysicsBody.DynamicFriction(collidingBody, collidingBody2, num5 - num2);
			float num19 = num16 * num18;
			if (collidingBody.type != 0 || collidingBody2.type != 0)
			{
				float num20 = 0f;
				if (collidingBody.type != 0)
				{
					num20 += 1f / num + num11 / num14;
				}
				if (collidingBody2.type != 0)
				{
					num20 += 1f / num4 + num11 / num15;
				}
				float b = Mathf.Abs(f) / num20;
				num19 = MathEx.Min(num19, b);
			}
			num19 *= Mathf.Sign(f);
			if (collidingBody.type != 0 && collidingBody.physicsDefinitions.applyThrow)
			{
				float num21 = num;
				float num22 = num14;
				Vector3 vector2 = num19 / num21 * vector;
				Vector3 vector3 = (0f - distanceToSurface) * num19 / num22 * Vector3.up;
				collision.body1.motionResolution.velocity += vector2;
				collision.body1.motionResolution.angularVelocity += vector3;
			}
			if (collidingBody2.type != 0 && collidingBody2.physicsDefinitions.applyThrow)
			{
				float num23 = num4;
				float num24 = num15;
				Vector3 vector4 = num19 / num23 * vector;
				Vector3 vector5 = (0f - distanceToSurface) * num19 / num24 * Vector3.up;
				collision.body2.motionResolution.velocity += vector4;
				collision.body2.motionResolution.angularVelocity += vector5;
			}
			Vector3 rhs = Vector3.Cross(collidingBody.myMotion.angularVelocity.OnGround(), collidingBody.shape.GetDistanceToSurface(Vector3.down) * Vector3.down);
			float num25 = Vector3.Dot(normalized, rhs);
			Vector3 rhs2 = Vector3.Cross(collidingBody2.myMotion.angularVelocity.OnGround(), collidingBody2.shape.GetDistanceToSurface(Vector3.down) * Vector3.down);
			float num26 = Vector3.Dot(normalized, rhs2);
			float f2 = num25 - num26;
			num19 = Mathf.Abs(num16) * num18;
			if (collidingBody.type != 0 || collidingBody2.type != 0)
			{
				float num27 = 0f;
				if (collidingBody.type != 0)
				{
					num27 += num11 / num14;
				}
				if (collidingBody2.type != 0)
				{
					num27 += num11 / num15;
				}
				float b2 = Mathf.Abs(f2) / num27;
				num19 = MathEx.Min(num19, b2);
			}
			if (collidingBody.type != 0)
			{
				Vector3 vector6 = (0f - Mathf.Sign(f2)) * num19 * distanceToSurface / num14 * Vector3.Cross(normalized, Vector3.up);
				collision.body1.motionResolution.angularVelocity += vector6;
			}
			if (collidingBody2.type != 0)
			{
				Vector3 vector7 = (0f - Mathf.Sign(f2)) * num19 * distanceToSurface / num15 * Vector3.Cross(normalized, Vector3.up);
				collision.body2.motionResolution.angularVelocity += vector7;
			}
		}
	}
}
